<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>高级纹理感图片渲染器</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            color: #e2e8f0;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 2rem;
            flex: 1;
        }

        h1 {
            text-align: center;
            margin-bottom: 2rem;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }

        .upload-area {
            border: 2px dashed #4a90e2;
            border-radius: 8px;
            padding: 2rem;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            margin-bottom: 2rem;
        }

        .upload-area:hover {
            background-color: rgba(74, 144, 226, 0.1);
            border-color: #90e24a;
        }

        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 1rem;
            margin-bottom: 2rem;
        }

        button,
        select {
            padding: 0.5rem 1rem;
            border: none;
            border-radius: 4px;
            background-color: #4a90e2;
            color: white;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        button:hover {
            background-color: #357abd;
        }

        .canvas-container {
            position: relative;
            background-color: rgba(0, 0, 0, 0.3);
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
        }

        canvas {
            display: block;
            max-width: 100%;
        }

        footer {
            text-align: center;
            padding: 1rem;
            background-color: rgba(0, 0, 0, 0.3);
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>高级纹理感图片渲染器</h1>

        <div class="upload-area" id="dropArea">
            <p>点击或拖拽图片到此处上传</p>
            <input type="file" id="fileInput" accept="image/*" style="display: none;">
        </div>

        <div class="controls">
            <button id="renderBtn" disabled>应用纹理效果</button>
            <select id="textureType">
                <option value="grain">颗粒感</option>
                <option value="marble">大理石纹</option>
                <option value="metallic">金属质感</option>
                <option value="watercolor">水彩效果</option>
            </select>
            <button id="downloadBtn" disabled>下载图aa片</button>
        </div>

        <div class="canvas-container">
            <canvas id="mainCanvas"></canvas>
        </div>
    </div>

    <footer>
        <p>高级纹理感图片渲染器 &copy; 2025</p>
    </footer>

    <script>
        const dropArea = document.getElementById('dropArea');
        const fileInput = document.getElementById('fileInput');
        const renderBtn = document.getElementById('renderBtn');
        const downloadBtn = document.getElementById('downloadBtn');
        const textureType = document.getElementById('textureType');
        const canvas = document.getElementById('mainCanvas');
        const ctx = canvas.getContext('2d');

        let originalImage = null;
        let textureIntensity = 0.4; // 纹理强度

        // 初始化
        function init() {
            // 点击上传区域打开文件选择对话框
            dropArea.addEventListener('click', () => fileInput.click());

            // 监听文件选择
            fileInput.addEventListener('change', handleFileSelect);

            // 拖放功能
            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                dropArea.addEventListener(eventName, preventDefaults, false);
            });

            function preventDefaults(e) {
                e.preventDefault();
                e.stopPropagation();
            }

            ['dragenter', 'dragover'].forEach(eventName => {
                dropArea.addEventListener(eventName, highlight, false);
            });

            ['dragleave', 'drop'].forEach(eventName => {
                dropArea.addEventListener(eventName, unhighlight, false);
            });

            function highlight() {
                dropArea.style.backgroundColor = 'rgba(74, 144, 226, 0.2)';
            }

            function unhighlight() {
                dropArea.style.backgroundColor = '';
            }

            dropArea.addEventListener('drop', handleDrop, false);

            function handleDrop(e) {
                const dt = e.dataTransfer;
                const file = dt.files[0];
                if (file && file.type.match('image.*')) {
                    handleImageFile(file);
                }
            }

            // 渲染按钮点击事件
            renderBtn.addEventListener('click', renderTexture);

            // 下载按钮点击事件
            downloadBtn.addEventListener('click', downloadImage);
        }

        // 处理文件选择
        function handleFileSelect(e) {
            const file = e.target.files[0];
            if (file && file.type.match('image.*')) {
                handleImageFile(file);
            }
        }

        // 处理图片文件
        function handleImageFile(file) {
            const reader = new FileReader();

            reader.onload = function (e) {
                const img = new Image();
                img.onload = function () {
                    // 设置Canvas尺寸与图片一致
                    canvas.width = img.width;
                    canvas.height = img.height;

                    // 保存原始图片
                    originalImage = img;

                    // 显示原始图片
                    ctx.drawImage(img, 0, 0);

                    // 启用按钮
                    renderBtn.disabled = false;
                    downloadBtn.disabled = false;
                };
                img.src = e.target.result;
            };

            reader.readAsDataURL(file);
        }

        // 生成噪点纹理
        function generateNoise(width, height) {
            const noiseCanvas = document.createElement('canvas');
            noiseCanvas.width = width;
            noiseCanvas.height = height;
            const noiseCtx = noiseCanvas.getContext('2d');
            const imageData = noiseCtx.createImageData(width, height);
            const data = imageData.data;

            for (let i = 0; i < data.length; i += 4) {
                const value = Math.floor(Math.random() * 256);
                data[i] = value;     // R
                data[i + 1] = value; // G
                data[i + 2] = value; // B
                data[i + 3] = 100;   // A (半透明)
            }

            noiseCtx.putImageData(imageData, 0, 0);
            return noiseCanvas;
        }

        // 渲染大理石纹理
        function generateMarbleTexture(width, height) {
            const textureCanvas = document.createElement('canvas');
            textureCanvas.width = width;
            textureCanvas.height = height;
            const textureCtx = textureCanvas.getContext('2d');

            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    // 基于正弦和余弦函数生成大理石纹理
                    const noise = Math.sin((x * 0.01) + Math.sin(y * 0.01) * 10) * 127 + 128;
                    const alpha = 80; // 透明度

                    // 基于位置生成微妙的颜色变化
                    const baseColor = Math.floor((x / width) * 50);
                    const r = Math.min(255, baseColor + noise * 0.2);
                    const g = Math.min(255, baseColor + 20 + noise * 0.2);
                    const b = Math.min(255, baseColor + 40 + noise * 0.2);

                    textureCtx.fillStyle = `rgba(${r}, ${g}, ${b}, ${alpha / 255})`;
                    textureCtx.fillRect(x, y, 1, 1);
                }
            }

            return textureCanvas;
        }

        // 渲染金属质感纹理
        function generateMetallicTexture(width, height) {
            const textureCanvas = document.createElement('canvas');
            textureCanvas.width = width;
            textureCanvas.height = height;
            const textureCtx = textureCanvas.getContext('2d');

            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    // 生成基本金属底色
                    const base = 150 + Math.sin(x * 0.05) * 20;

                    // 添加精细的金属颗粒
                    const grain = Math.random() * 30 - 15;

                    // 添加光泽效果
                    const shine = Math.sin((x + y) * 0.02) * 20;

                    const value = Math.min(255, Math.max(0, base + grain + shine));
                    const alpha = 60; // 透明度

                    textureCtx.fillStyle = `rgba(${value}, ${value}, ${value}, ${alpha / 255})`;
                    textureCtx.fillRect(x, y, 1, 1);
                }
            }

            return textureCanvas;
        }

        // 渲染水彩效果纹理
        function generateWatercolorTexture(width, height) {
            const textureCanvas = document.createElement('canvas');
            textureCanvas.width = width;
            textureCanvas.height = height;
            const textureCtx = textureCanvas.getContext('2d');

            // 创建基础色层
            const gradient = textureCtx.createLinearGradient(0, 0, width, height);
            gradient.addColorStop(0, 'rgba(135, 206, 235, 0.1)');
            gradient.addColorStop(0.5, 'rgba(173, 216, 230, 0.1)');
            gradient.addColorStop(1, 'rgba(135, 206, 250, 0.1)');

            textureCtx.fillStyle = gradient;
            textureCtx.fillRect(0, 0, width, height);

            // 添加随机水彩斑点
            for (let i = 0; i < 100; i++) {
                const x = Math.random() * width;
                const y = Math.random() * height;
                const radius = Math.random() * 30 + 10;

                const colors = [
                    'rgba(135, 206, 235, 0.2)',
                    'rgba(173, 216, 230, 0.2)',
                    'rgba(135, 206, 250, 0.2)',
                    'rgba(70, 130, 180, 0.2)'
                ];

                const color = colors[Math.floor(Math.random() * colors.length)];

                textureCtx.fillStyle = color;
                textureCtx.beginPath();
                textureCtx.arc(x, y, radius, 0, Math.PI * 2);
                textureCtx.fill();
            }

            return textureCanvas;
        }

        // 渲染纹理效果
        function renderTexture() {
            if (!originalImage) return;

            // 清除画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 绘制原始图像
            ctx.drawImage(originalImage, 0, 0);

            // 根据选择的纹理类型生成纹理
            let textureCanvas;
            switch (textureType.value) {
                case 'grain':
                    textureCanvas = generateNoise(canvas.width, canvas.height);
                    break;
                case 'marble':
                    textureCanvas = generateMarbleTexture(canvas.width, canvas.height);
                    break;
                case 'metallic':
                    textureCanvas = generateMetallicTexture(canvas.width, canvas.height);
                    break;
                case 'watercolor':
                    textureCanvas = generateWatercolorTexture(canvas.width, canvas.height);
                    break;
                default:
                    textureCanvas = generateNoise(canvas.width, canvas.height);
            }

            // 应用纹理叠加
            ctx.save();
            ctx.globalAlpha = textureIntensity;

            // 根据纹理类型选择不同的混合模式
            switch (textureType.value) {
                case 'grain':
                case 'metallic':
                    ctx.globalCompositeOperation = 'overlay';
                    break;
                case 'marble':
                    ctx.globalCompositeOperation = 'soft-light';
                    break;
                case 'watercolor':
                    ctx.globalCompositeOperation = 'multiply';
                    break;
            }

            ctx.drawImage(textureCanvas, 0, 0);
            ctx.restore();

            // 添加最终的细节调整
            applyFinalTouches();
        }

        // 应用最终调整
        function applyFinalTouches() {
            // 创建临时画布进行图像处理
            const tempCanvas = document.createElement('canvas');
            tempCanvas.width = canvas.width;
            tempCanvas.height = canvas.height;
            const tempCtx = tempCanvas.getContext('2d');

            // 将当前画布内容复制到临时画布
            tempCtx.drawImage(canvas, 0, 0);

            // 获取图像数据
            const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
            const data = imageData.data;

            // 根据纹理类型进行不同的后期处理
            switch (textureType.value) {
                case 'grain':
                case 'metallic':
                    // 增加对比度
                    for (let i = 0; i < data.length; i += 4) {
                        data[i] = Math.pow(data[i] / 255, 1.2) * 255;     // R
                        data[i + 1] = Math.pow(data[i + 1] / 255, 1.2) * 255; // G
                        data[i + 2] = Math.pow(data[i + 2] / 255, 1.2) * 255; // B
                    }
                    break;
                case 'marble':
                    // 柔化边缘
                    // 这里简化处理，实际应该使用卷积滤镜
                    break;
                case 'watercolor':
                    // 增加饱和度
                    for (let i = 0; i < data.length; i += 4) {
                        const r = data[i];
                        const g = data[i + 1];
                        const b = data[i + 2];

                        // 计算亮度
                        const l = 0.2126 * r + 0.7152 * g + 0.0722 * b;

                        // 增加饱和度
                        data[i] = Math.min(255, l + (r - l) * 1.2);     // R
                        data[i + 1] = Math.min(255, l + (g - l) * 1.2); // G
                        data[i + 2] = Math.min(255, l + (b - l) * 1.2); // B
                    }
                    break;
            }

            // 将处理后的图像数据放回临时画布
            tempCtx.putImageData(imageData, 0, 0);

            // 将临时画布内容绘制回主画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(tempCanvas, 0, 0);
        }

        // 下载图片
        function downloadImage() {
            if (!canvas.toBlob) {
                alert('您的浏览器不支持下载功能');
                return;
            }

            canvas.toBlob(function (blob) {
                const link = document.createElement('a');
                link.href = URL.createObjectURL(blob);
                link.download = 'texture-image.png';
                link.click();

                // 清理
                setTimeout(() => {
                    URL.revokeObjectURL(link.href);
                }, 100);
            });
        }

        // 响应式处理
        function handleResize() {
            // 保持Canvas的纵横比，但限制最大宽度
            if (originalImage) {
                const maxWidth = Math.min(window.innerWidth - 40, 1200);
                const ratio = originalImage.width / originalImage.height;

                if (originalImage.width > maxWidth) {
                    canvas.width = maxWidth;
                    canvas.height = maxWidth / ratio;
                } else {
                    canvas.width = originalImage.width;
                    canvas.height = originalImage.height;
                }

                // 重新绘制图像
                ctx.drawImage(originalImage, 0, 0, canvas.width, canvas.height);
            }
        }

        // 监听窗口大小变化
        window.addEventListener('resize', handleResize);

        // 初始化应用
        init();
    </script>
</body>

</html>